//
//  Simulation.cpp
//  Texture
//
//  Created by Yao Melo on 12/29/12.
//
//

#include "Simulation.h"
//#include "ResourceFile.h"
//#include "GraphicsDevice.h"
//#import <OpenGLES/EAGL.h>


Simulation::Simulation()
{
//    _beeRaid = new std::vector<SimBee>;

    ship = new SimShip();
    invaders = new vector<SimInvader>();
    for(int row = 0;row< INVADER_ROWS;row++)
    {
        for(int column = 0;column< INVADER_COLUMNS;column++)
        {
            SimInvader invader(Vec3(-PlAYFEILD_X_MAX/2+column*2.0f, 0, PlAYFEILD_Z_MIN + row*2.0f));
            invaders->push_back(invader);
        }
    }
    shots = new vector<SimShot>();
    explosions = new vector<SimExplosion>();
    shipShotIndex = -1;
    score = 0;
    gameState = eStatePlaying;
}

Simulation::~Simulation()
{
    delete ship;
    delete invaders;
    delete shots;
    delete explosions;
   
}

void Simulation::UpdateInvaders(float delta)
{
    for(vector<SimInvader>::iterator it = invaders->begin();it!=invaders->end();)
    {
        (*(it++)).Update(delta*speedMultiplier);
    }

}

void Simulation::UpdateExplosions(float delta)
{
    for(vector<SimExplosion>::iterator it = explosions->begin();it!=explosions->end();)
    {
        (*it).Update(delta);

        if((*it).aliveTime > EXPLOSION_DURATION)
        {
            it = explosions -> erase(it);
        }
        else
        {
            it++;
        }
    }
}

void Simulation::UpdateShots(float delta)
{
    int index = -1;
    for(vector<SimShot>::iterator it = shots->begin();it!=shots->end();)
    {
        it->Update(delta);
        if(!it->isFromInvader&&!it->hasLeftField)
        {
            index = it - shots->begin();
        }
        it++;
    }
    shipShotIndex = index;

    for(vector<SimShot>::iterator it = shots->begin();it!=shots->end();)
    {
        if((*it).hasLeftField)
        {
            it = shots->erase(it);
        }
        else
        {
            it++;
        }
    }
    if(invaders->size() > 0 &&  rand() < 0.003f * RAND_MAX * speedMultiplier*invaders->size())
    {
        int index = (int)(((long long)rand()) * (invaders -> size()) / RAND_MAX);

        SimShot shot((*invaders)[index].position,true);
        shots -> push_back(shot);
    }
}


void Simulation::CheckInvaderCollision()
{
    if(shipShotIndex < 0)
    {
        return;
    }
    for(vector<SimInvader>::iterator it = invaders->begin();it!=invaders->end();)
    {
        SimInvader invader = *it;
        Vec3 dstVec = invader.position - (*shots)[shipShotIndex].position;
        if(dstVec.length() < INVADER_RADIUS) //collision detected.
        {
//            for(vector<SimShot>::iterator shotIt=shots->begin();shotIt!=shots->end();)
//            {
//                if(!(*shotIt).isFromInvader)
//                {
//                    shotIt = shots->erase(shotIt);
//                    break;
//                }
//                else
//                {
//                    shotIt++;
//                }
//            }
//            delete shipShot;
            shots->erase(shots->begin()+shipShotIndex);
            shipShotIndex = -1;
            explosions -> push_back(SimExplosion(invader.position));
            it = invaders->erase(it);
            score += INVADER_SCORE;
            break;
        }
        else
        {
            it++;
        }
    }
}

void Simulation::CheckShipCollision()
{
    if(!ship->isExploding)
    {
        for(vector<SimShot>::iterator it = shots->begin();it!=shots->end();)
        {
            SimShot shot = *it;
            if(shot.isFromInvader)
            {
                Vec3 dstVec = shot.position - ship->position;
                if(dstVec.length() < SHIP_RADIUS)
                {
                    ship->lives --;
                    ship->isExploding = true;
                    shot.hasLeftField = true;
                    it = shots->erase(it);
                    explosions -> push_back(SimExplosion(ship->position));
                    break;
                }
            }
            it++;
        }
        for(vector<SimInvader>::iterator it = invaders->begin();it!=invaders->end();)
        {
            if((*it).position.z < PlAYFEILD_Z_MIN)
            {
                ship->lives --;
                ship->isExploding = true;
                explosions -> push_back(SimExplosion(ship->position));
                break;
            }
            it++;
        }
    }
}

void Simulation::CheckGameState()
{
    if(ship->lives == 0 && !ship->isExploding)
    {
        gameState = eStateGameover;
    }
    else if(invaders ->size() == 0)
    {
        gameState = eStateWin;
    }
}

void Simulation::Update(float t)
{
    printf("delta t:%f\n",t);
    ship -> Update(t);
    UpdateInvaders(t);
    UpdateShots(t);
    UpdateExplosions(t);
    CheckShipCollision();
    CheckInvaderCollision();
    CheckGameState();
}


void Simulation::MoveLeft(float delta)
{
    if(ship->isExploding)
    {
        return;
    }
    
    ship->position.x-=delta*SHIP_VELOCITY;
    if(ship->position.x < PlAYFEILD_X_MIN)
    {
        ship->position.x = PlAYFEILD_X_MIN;
    }
    printf("moving left:%f, ship final X:%f\n",delta*SHIP_VELOCITY, ship->position.x);
}

void Simulation::MoveRight(float delta)
{
    if(ship->isExploding)
    {
        return;
    }
    ship->position.x+=delta*SHIP_VELOCITY;
    if(ship->position.x > PlAYFEILD_X_MAX)
    {
        ship->position.x = PlAYFEILD_X_MAX;
    }
        printf("moving right:%f, ship final X:%f\n",delta*SHIP_VELOCITY, ship->position.x);
}

void Simulation::Shot()
{
    if (shipShotIndex<0 && !ship->isExploding) {
        SimShot shot(ship->position, false);
        shots->push_back(shot);
    }
}